home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload Trio 2
/
Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO
/
dir34
/
thindi.zip
/
THISRC.ZIP
/
STATBAR.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-19
|
21KB
|
602 lines
//===========================================================
// StatBar - A set of routines that adds a status bar to a
// client window.
// Copyright (C) 1993 Douglas Boling
//
// To Use:
// Include Statbar.h in source file
//
//
//
// Revision History:
//
// 1.0 Initial Release
//===========================================================
// Returns no. of elements
#define dim(x) (sizeof(x) / sizeof(x[0]))
#include "windows.h"
#include "string.h"
#include "stdlib.h"
#define INT int
#define UINT WORD
#define APIENTRY PASCAL
#define WNDPROC FARPROC
#include "statbar.h"
#define TEXTBUFFSIZE 512
struct decodeUINT { // structure associates
UINT Code; // messages
LONG (*Fxn)(HWND, UINT, UINT, LONG); // with a function
};
typedef struct {
INT sWidth;
char far *lpszText;
} FIELDENT;
typedef struct {
HFONT hFont;
INT sHeight;
LPSTR lpEnd;
INT sFreeSpace;
INT sNumFields;
FIELDENT feField[1];
} STATUSBARDATA;
typedef STATUSBARDATA far * LPSTATUSBARDATA;
//-----------------------------------------------------------
// NonPublic procedure declarations
//----------------------------------------------------------
// Message handler functions for client subclass proc
LONG DoSizeClient (HWND, UINT, UINT, LONG);
LONG DoMenuSelectClient (HWND, UINT, UINT, LONG);
LONG DoDestroyClient (HWND, UINT, UINT, LONG);
// Message handler functions for status bar window proc
LONG DoSetTextStatBar (HWND, UINT, UINT, LONG);
LONG DoGetTextStatBar (HWND, UINT, UINT, LONG);
LONG DoPaintStatBar (HWND, UINT, UINT, LONG);
//LONG DoSizeStatBar (HWND, UINT, UINT, LONG);
LONG DoDestroyStatBar (HWND, UINT, UINT, LONG);
//Status bar functions
HFONT GetStatusBarFont (void);
void GetFieldRect (LPSTATUSBARDATA, INT, RECT *, RECT *);
void DrawFieldText (LPSTATUSBARDATA, HWND, LPSTR, RECT *);
void DrawSBText (HWND, char far *, INT);
void Draw3DRect (HDC, HPEN, HPEN, RECT *);
// Utility routines
WNDPROC MySubClassWindow (HWND, WNDPROC);
//-----------------------------------------------------------
// Global data
//-----------------------------------------------------------
// Message dispatch table for ClientSCProc
struct decodeUINT ClientSCMessages[] = {
WM_SIZE, DoSizeClient,
WM_MENUSELECT, DoMenuSelectClient,
WM_DESTROY, DoDestroyClient,
};
// Message dispatch table for StatbarWndProc
struct decodeUINT StatBarMessages[] = {
WM_SETTEXT, DoSetTextStatBar,
WM_GETTEXT, DoGetTextStatBar,
WM_PAINT, DoPaintStatBar,
WM_DESTROY, DoDestroyStatBar,
};
HANDLE hInst;
FARPROC lpfnClientSCProc, lpfnOldClientWndProc;
//============================================================
// Status Bar Public functions
//============================================================
//-----------------------------------------------------------
// StatusBarInit - Initialization code for the status bar.
//-----------------------------------------------------------
INT StatusBarInit(HANDLE hInstance) {
WNDCLASS wc;
hInst = hInstance;
//
// Register status bar window class
//
wc.style = CS_HREDRAW; // Class style
wc.lpfnWndProc = StatBarWinProc; // Callback function
wc.cbClsExtra = 0; // Extra class data
wc.cbWndExtra = sizeof (HGLOBAL); // Extra window data
wc.hInstance = hInst; // Owner handle
wc.hIcon = 0; // Application icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Default cursor
wc.hbrBackground = CreateSolidBrush (GetSysColor (COLOR_BTNFACE));
wc.lpszMenuName = 0; // Menu name
wc.lpszClassName = "StatusBarCls"; // Window class name
if (RegisterClass(&wc) == 0)
return 1;
return 0;
}
//-----------------------------------------------------------
// StatusBarCreate - Creates a status bar window
//-----------------------------------------------------------
INT StatusBarCreate (HWND hWndClient, INT sNumFields, INT *sFieldArray) {
INT x, y, cx, cy;
HWND hwndStatBar;
RECT rect;
HGLOBAL hData;
LPSTATUSBARDATA lpStatData;
//
//Alloc memory for status window info block
//
hData = GlobalAlloc (GHND, sizeof (STATUSBARDATA) +
sNumFields * sizeof(FIELDENT) +
TEXTBUFFSIZE);
if (!hData)
return 11;
lpStatData = (LPSTATUSBARDATA) GlobalLock (hData);
//
//Init memory block
//
lpStatData->sFreeSpace = TEXTBUFFSIZE;
lpStatData->lpEnd = (LPSTR) lpStatData + sizeof (STATUSBARDATA) +
sNumFields * sizeof(FIELDENT);
lpStatData->sNumFields = sNumFields;
for (x = 0; x < sNumFields; x++) {
lpStatData->feField[x].sWidth = sFieldArray[x];
lpStatData->feField[x].lpszText = 0;
}
//
//Create the status bar font
//
lpStatData->hFont = GetStatusBarFont ();
lpStatData->sHeight = GetStatusBarHeight ();
//
// Create status bar window
//
GetClientRect (hWndClient, &rect);
x = rect.left;
y = rect.bottom - lpStatData->sHeight;
cx = rect.right - rect.left;
cy = lpStatData->sHeight;
hwndStatBar = CreateWindow ("StatusBarCls", NULL,
WS_CHILD | WS_VISIBLE, x, y, cx, cy,
hWndClient, IDD_STATBAR, hInst, NULL);
if(!hwndStatBar) {
OutputDebugString ("Status Bar create fail\n");
return 0x10;
}
SetWindowWord (hwndStatBar, 0, hData);
GlobalUnlock (hData);
lpfnClientSCProc = MakeProcInstance ((FARPROC) ClientSCProc, hInst);
lpfnOldClientWndProc = MySubClassWindow (hWndClient, lpfnClientSCProc);
return 0; // return success flag
}
//------------------------------------------------------------
// GetStatusBarHeight - returns the height of the status bar
//------------------------------------------------------------
INT GetStatusBarHeight (void) {
HDC hdc;
HFONT hFont, hOld;
TEXTMETRIC tm;
//
//Create the status bar font and compute its size
//
hFont = GetStatusBarFont ();
hdc = GetDC(NULL);
hOld = SelectObject(hdc, hFont);
GetTextMetrics(hdc, &tm);
SelectObject(hdc, hOld);
DeleteObject (hFont);
ReleaseDC(NULL, hdc);
return tm.tmHeight + tm.tmExternalLeading + 10;
}
//------------------------------------------------------------
// ModifyClientRect - Modifies a rect structure filled with
// the client window dimentions to reflect the status bar
//------------------------------------------------------------
INT ModifyClientRect (HWND hWnd, RECT *rectOut) {
RECT rect;
HWND hwndStatBar;
hwndStatBar = GetDlgItem (hWnd, IDD_STATBAR);
if (hwndStatBar == 0)
return 0;
GetClientRect (hwndStatBar, &rect);
rectOut->bottom -= (rect.bottom - rect.top);
return 0;
}
//------------------------------------------------------------
// SetStatusBarLong - Displays a number in a status bar field
// status bar.
//------------------------------------------------------------
INT SetStatusBarLong (HWND hWnd, char *pszText, LONG lNum, INT sField) {
char szTemp[256];
strcpy (szTemp, pszText);
ltoa (lNum, &szTemp[strlen(szTemp)], 10);
return SetStatusBarText (hWnd, szTemp, sField);
}
//------------------------------------------------------------
// SetStatusBarText - Sets the texts for a field in the
// status bar.
//------------------------------------------------------------
INT SetStatusBarText (HWND hWnd, char *pszText, INT sField) {
HWND hwndStatBar;
LPSTATUSBARDATA lpStatData;
INT i, sLen, sSrcLen;
LPSTR lpSrc;
LPSTR lpDest;
hwndStatBar = GetDlgItem (hWnd, IDD_STATBAR);
if (hwndStatBar == 0)
return 1;
lpStatData = (LPSTATUSBARDATA) GlobalLock (GetWindowWord (hwndStatBar, 0));
//
//Copy the text into the status bar global buffer
//
if (lpStatData->feField[sField].lpszText != 0) {
//
//If field already has text, remove and collapse the buffer
//strings over the string being removed.
//
lpDest = lpStatData->feField[sField].lpszText;
sLen = lstrlen (lpDest) + 1;
lpSrc = lpDest + sLen;
while (lpSrc < lpStatData->lpEnd) {
//
//Search array for pointer to this string
//
for (i = 0; i < lpStatData->sNumFields; i++)
if (lpSrc == lpStatData->feField[i].lpszText)
break;
//
//Move string and update pointer.
//
lpStatData->feField[i].lpszText = lpDest;
lstrcpy (lpDest, lpSrc);
sSrcLen = lstrlen (lpSrc) + 1;
lpDest += sSrcLen;
lpSrc += sSrcLen;
}
lpStatData->lpEnd = lpDest;
lpStatData->sFreeSpace += sLen;
}
sLen = strlen (pszText) + 1;
if (sLen < lpStatData->sFreeSpace) {
lstrcpy (lpStatData->lpEnd, pszText);
lpStatData->feField[sField].lpszText = lpStatData->lpEnd;
lpStatData->lpEnd += sLen;
lpStatData->sFreeSpace -= sLen;
} else
return 2;
return DrawSBText (hwndStatBar, pszText, sField);
}
//============================================================
// Client window subclass procedures
//============================================================
//------------------------------------------------------------
// ClientSCProc - Callback subclass function for client window
//------------------------------------------------------------
LONG CALLBACK ClientSCProc(HWND hWnd, UINT wMsg, UINT wParam,
LONG lParam) {
INT i;
//
// Search message list to see if we need to handle this
// message. If in list, call procedure.
//
for(i = 0; i < dim(ClientSCMessages); i++) {
if(wMsg == ClientSCMessages[i].Code)
return (*ClientSCMessages[i].Fxn)(hWnd, wMsg, wParam, lParam);
}
return CallWindowProc (lpfnOldClientWndProc, hWnd, wMsg,
wParam, lParam);
}
//------------------------------------------------------------
// DoSizeClient - process WM_SIZE message for client window.
//------------------------------------------------------------
LONG DoSizeClient (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) {
INT x,y, cx, cy;
RECT rect;
LPSTATUSBARDATA lpStatData;
HGLOBAL hData;
HWND hwndStatBar;
hwndStatBar = GetDlgItem (hWnd, IDD_STATBAR);
if (hwndStatBar == 0)
return CallWindowProc (lpfnOldClientWndProc, hWnd, wMsg,
wParam, lParam);
hData = GetWindowWord (hwndStatBar, 0);
lpStatData = (LPSTATUSBARDATA) GlobalLock (hData);
// Compute size of window
GetClientRect (hWnd, &rect);
x = rect.left;
y = rect.bottom - lpStatData->sHeight;
cx = rect.right - rect.left;
cy = lpStatData->sHeight;
SetWindowPos (hwndStatBar, NULL, x, y, cx, cy, SWP_NOZORDER);
GlobalUnlock (hData);
return CallWindowProc (lpfnOldClientWndProc, hWnd, wMsg,
wParam, lParam);
}
//------------------------------------------------------------
// DoMenuSelectClient - process WM_MENUSELECT message for client window.
//------------------------------------------------------------
LONG DoMenuSelectClient (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) {
HWND hwndStatBar;
char szText[128];
UINT usFlags, usMenu;
LPSTATUSBARDATA lpStatData;
hwndStatBar = GetDlgItem (hWnd, IDD_STATBAR);
if (hwndStatBar == 0)
return CallWindowProc (lpfnOldClientWndProc, hWnd, wMsg,
wParam, lParam);
usFlags = LOWORD (lParam);
usMenu = wParam;
szText[0] = '\0';
if ((usFlags & MF_SYSMENU) && (usMenu == NULL)) {
lpStatData = (LPSTATUSBARDATA) GlobalLock (GetWindowWord (hwndStatBar, 0));
if (lpStatData->feField[0].lpszText)
DrawSBText (hwndStatBar, lpStatData->feField[0].lpszText, 0);
else
DrawSBText (hwndStatBar, "", 0);
GlobalUnlock (GetWindowWord (hwndStatBar, 0));
} else if (!(usFlags & MF_SEPARATOR)) {
if ((usFlags & MF_SYSMENU) && (usFlags & MF_POPUP))
LoadString (hInst, IDM_SYSMENUACTIVE, szText, sizeof (szText));
else if (!(usFlags & MF_POPUP))
LoadString (hInst, usMenu+MENUTEXT, szText, sizeof (szText));
DrawSBText (hwndStatBar, szText, 0);
}
return CallWindowProc (lpfnOldClientWndProc, hWnd, wMsg,
wParam, lParam);
}
//------------------------------------------------------------
// DoDestroyClient - process WM_DESTROY message for client window.
//------------------------------------------------------------
LONG DoDestroyClient (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) {
LONG lRC;
DestroyWindow (GetDlgItem (hWnd, IDD_STATBAR));
lRC = CallWindowProc (lpfnOldClientWndProc, hWnd, wMsg,
wParam, lParam);
MySubClassWindow (hWnd, lpfnOldClientWndProc);
FreeProcInstance ((FARPROC) lpfnClientSCProc);
return lRC;
}
//============================================================
// Status Bar Window functions
//============================================================
//------------------------------------------------------------
// StatBarWinProc - Callback function for status bar window
//------------------------------------------------------------
LONG CALLBACK StatBarWinProc(HWND hWnd, UINT wMsg, UINT wParam,
LONG lParam) {
INT i;
//
// Search message list to see if we need to handle this
// message. If in list, call procedure.
//
for(i = 0; i < dim(StatBarMessages); i++) {
if(wMsg == StatBarMessages[i].Code)
return (*StatBarMessages[i].Fxn)(hWnd, wMsg, wParam, lParam);
}
return DefWindowProc(hWnd, wMsg, wParam, lParam);
}
//------------------------------------------------------------
// DoSetTextStatBar - process WM_SETTEXT message for StatBar window.
// Place default text in field 0
//------------------------------------------------------------
LONG DoSetTextStatBar (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) {
char szTemp[256];
lstrcpyn (szTemp, (LPSTR) lParam, sizeof (szTemp) - 1);
szTemp[255] = '\0';
SetStatusBarText (GetParent (hWnd), szTemp, 0);
return 0;
}
//------------------------------------------------------------
// DoGetTextStatBar - process WM_GETTEXT message for StatBar window.
// Return text from field 0
//------------------------------------------------------------
LONG DoGetTextStatBar (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) {
LPSTATUSBARDATA lpStatData;
UINT usLen;
LPSTR lpSrc;
lpStatData = (LPSTATUSBARDATA) GlobalLock (GetWindowWord (hWnd, 0));
//
//Copy the text into the status bar global buffer
//
usLen = 0;
if (lpStatData->feField[0].lpszText != 0) {
lpSrc = lpStatData->feField[0].lpszText;
usLen = min ((UINT)lstrlen (lpSrc), wParam-1);
lstrcpyn ((LPSTR) lParam, lpSrc, usLen);
*((LPSTR)lParam+usLen) = '\0';
}
GlobalUnlock (GetWindowWord (hWnd, 0));
return usLen;
}
//------------------------------------------------------------
// DoPaintStatBar - process WM_PAINT message for StatBar window.
//------------------------------------------------------------
LONG DoPaintStatBar (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) {
INT i;
LPSTATUSBARDATA lpStatData;
HDC hdc;
PAINTSTRUCT ps;
RECT rect, rectOut;
HPEN hLPen, hDPen, hOldPen;
lpStatData = (LPSTATUSBARDATA) GlobalLock (GetWindowWord (hWnd, 0));
GetClientRect (hWnd, &rect);
hdc = BeginPaint (hWnd, &ps);
hDPen = CreatePen (PS_SOLID, 1, GetSysColor (COLOR_BTNSHADOW));
hLPen = CreatePen (PS_SOLID, 1, GetSysColor (COLOR_BTNHIGHLIGHT));
//
//Draw sep line across the top of the status bar
//
hOldPen = SelectObject (hdc, hDPen);
MoveTo (hdc, rect.left, rect.top);
LineTo (hdc, rect.right, rect.top);
SelectObject (hdc, hLPen);
MoveTo (hdc, rect.left, rect.top+1);
LineTo (hdc, rect.right, rect.top+1);
SelectObject (hdc, hOldPen);
//
//Draw the individual fields
//
for (i = 0; i < lpStatData->sNumFields; i++) {
GetFieldRect (lpStatData, i, &rect, &rectOut);
Draw3DRect (hdc, hDPen, hLPen, &rectOut);
DrawFieldText (lpStatData, hWnd, lpStatData->feField[i].lpszText,
&rectOut);
}
DeleteObject (hDPen);
DeleteObject (hLPen);
EndPaint (hWnd, &ps);
GlobalUnlock (GetWindowWord (hWnd, 0));
return 0;
}
//------------------------------------------------------------
// DoDestroyStatBar - process WM_DESTROY message for status bar
// window.
//------------------------------------------------------------
LONG DoDestroyStatBar (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) {
LPSTATUSBARDATA lpStatData;
lpStatData = (LPSTATUSBARDATA) GlobalLock (GetWindowWord (hWnd, 0));
DeleteObject (lpStatData->hFont);
GlobalUnlock (GetWindowWord (hWnd, 0));
GlobalFree (GetWindowWord (hWnd, 0));
return DefWindowProc(hWnd, wMsg, wParam, lParam);
}
//------------------------------------------------------------
// GetStatusBarFont - returns a font handle for the status
// bar font.
//------------------------------------------------------------
HFONT GetStatusBarFont (void) {
HDC hdc;
INT sFHeight;
//
//Create the status bar font and compute its size
//
hdc = GetDC(NULL);
sFHeight = MulDiv(-10, GetDeviceCaps(hdc, LOGPIXELSY), 72);
ReleaseDC(NULL, hdc);
return CreateFont(sFHeight, 0, 0, 0, FW_BOLD, 0, 0, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "Helv");
}
//------------------------------------------------------------
// DrawFieldText - Draws text in a status bar field
//------------------------------------------------------------
void DrawFieldText (LPSTATUSBARDATA lpStatData, HWND hWnd,
LPSTR lpszText, RECT *rect) {
HDC hdc;
HFONT hOldFont;
rect->top += 2;
rect->bottom -= 2;
rect->left += 5;
rect->right -= 5;
hdc = GetDC (hWnd);
hOldFont = SelectObject (hdc, lpStatData->hFont);
SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
SetBkColor (hdc, GetSysColor (COLOR_BTNFACE));
if (lpszText)
ExtTextOut (hdc, rect->left, rect->top, ETO_CLIPPED | ETO_OPAQUE,
rect, lpszText, lstrlen (lpszText), NULL);
else
ExtTextOut (hdc, rect->left, rect->top, ETO_CLIPPED | ETO_OPAQUE,
rect, "", 0, NULL);
SelectObject (hdc, hOldFont);
ReleaseDC (hWnd, hdc);
return;
}
//------------------------------------------------------------
// GetFieldRect - Computes the rectangle for a given field.
//------------------------------------------------------------
void GetFieldRect (LPSTATUSBARDATA lpStatData, INT sField,
RECT *rect, RECT *rectOut) {
INT i, sRight;
*rectOut = *rect;
rectOut->top += 3;
rectOut->bottom -= 3;
rectOut->left += 3;
rectOut->right -= 3;
sRight = rectOut->right;
for (i = 0; i < sField; i++)
if (lpStatData->feField[i].sWidth)
rectOut->left += lpStatData->feField[i].sWidth + 3;
else
break;
if (lpStatData->feField[i].sWidth == 0) {
for (i = lpStatData->sNumFields - 1; i > sField; i--)
rectOut->right -= lpStatData->feField[i].sWidth + 3;
if (lpStatData->feField[sField].sWidth != 0)
rectOut->left = rectOut->right - lpStatData->feField[sField].sWidth;
} else if (sField == lpStatData->sNumFields - 1)
rectOut->right = sRight;
else
rectOut->right = rectOut->left + lpStatData->feField[i].sWidth - 3;
return;
}
//------------------------------------------------------------
// DrawSBText - Displays text in a status bar field
//------------------------------------------------------------
void DrawSBText (HWND hWnd, char far *lpszText, INT sField) {
LPSTATUSBARDATA lpStatData;
RECT rect;
lpStatData = (LPSTATUSBARDATA) GlobalLock (GetWindowWord (hWnd, 0));
GetClientRect (hWnd, &rect);
GetFieldRect (lpStatData, sField, &rect, &rect);
DrawFieldText (lpStatData, hWnd, lpszText, &rect);
GlobalUnlock (GetWindowWord (hWnd, 0));
return;
}
//------------------------------------------------------------
// Draw3DRect - Routine that draws a 3D effect rectangle
//------------------------------------------------------------
void Draw3DRect (HDC hdc, HPEN hDPen, HPEN hLPen, RECT *rect) {
HPEN hOldPen;
//Start at bottom left, draw dark pen up and over top.
hOldPen = SelectObject (hdc, hDPen);
MoveTo (hdc, rect->left, rect->bottom);
LineTo (hdc, rect->left, rect->top);
LineTo (hdc, rect->right+1, rect->top);
//Start at bottom left, draw light pen over and up.
SelectObject (hdc, hLPen);
MoveTo (hdc, rect->left+1, rect->bottom);
LineTo (hdc, rect->right, rect->bottom);
LineTo (hdc, rect->right, rect->top);
SelectObject (hdc, hOldPen);
}
//============================================================
// General Helper Routines
//============================================================